package com.winit.openapi.oauth.controller;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSONObject;
import com.winit.openapi.constants.ErrorCode;
import com.winit.openapi.controller.BaseController;
import com.winit.openapi.exception.ApiException;
import com.winit.openapi.model.RequestMsg;
import com.winit.openapi.model.ResponseMsg;
import com.winit.openapi.oauth.util.OAuth2SecurityUtil;
import com.winit.openapi.upush2.sender.APIMonitoringEmailSender;
import com.winit.openapi.upush2.sender.UPushMessageModel;
import com.winit.openapi.util.RedisUtil;
import com.winit.openapi.util.SignUtil;
import com.winit.openapi.util.ValidateUtil;

@Controller
@RequestMapping(value = "/winit/oauth/tools")
public class APIOAuthToolsController extends BaseController {

    @Resource
    private APIMonitoringEmailSender emailSender;

    @RequestMapping(value = "/code/verification")
    public String verification(@ModelAttribute RequestMsg requestMsg) {
        Object obj = requestMsg.getData();
        if (obj instanceof JSONObject) {
            JSONObject json = (JSONObject) obj;
            ValidateUtil.validNotNull(json, "key");
            ValidateUtil.validMaxLength(json, "code", 100, true);
            ValidateUtil.validNotNull(json, "code");
            String key = json.getString("key");
            String code = json.getString("code");

            String codeCache = RedisUtil.get(key);
            if (StringUtils.isBlank(codeCache) || !code.equals(codeCache)) {
                throw new ApiException(ErrorCode.OAUTH_VERIFICATION_CODE_ERROR);
            }

        } else {
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }

        return SUCCESS;

    }

    @RequestMapping(value = "/send/sms")
    public String smsVerification(@ModelAttribute RequestMsg requestMsg) {
        Object obj = requestMsg.getData();
        if (obj instanceof JSONObject) {
            JSONObject json = (JSONObject) obj;
            ValidateUtil.validNotNull(json, "mobilePhone");
            ValidateUtil.validMaxLength(json, "mobilePhone", 30, true);
            ValidateUtil.validNotNull(json, "body");
            ValidateUtil.validMaxLength(json, "body", 256, true);
            String mobile = json.getString("mobilePhone");
            String body = json.getString("body");
            UPushMessageModel smsModel = new UPushMessageModel();
            smsModel.setTo(mobile);
            smsModel.setSendType("SMS");
            String code = OAuth2SecurityUtil.generateFixLenthRandomString(6);
            String bodyFormat = MessageFormat.format(body, code);
            smsModel.setBody(bodyFormat);
            try {
                emailSender.pushMsg(smsModel);
            } catch (Exception e) {
                throw new ApiException(ErrorCode.OAUTH_PUSH_MSG_ERROR);
            }
            RedisUtil.put(json.getString("mobilePhone"), code, 5 * 60);

        } else {
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }
        return SUCCESS;
    }

    @RequestMapping(value = "/send/email")
    public String emailVerification(@ModelAttribute RequestMsg requestMsg) {
        Object obj = requestMsg.getData();
        if (obj instanceof JSONObject) {
            JSONObject json = (JSONObject) obj;
            ValidateUtil.validNotNull(json, "email");
            ValidateUtil.validMaxLength(json, "email", 100, true);
            validateEmail(json.getString("email"), "email");
            ValidateUtil.validNotNull(json, "subject");
            ValidateUtil.validMaxLength(json, "subject", 256, true);
            ValidateUtil.validNotNull(json, "body");
            ValidateUtil.validMaxLength(json, "body", 256, true);
            if (json.containsKey("bc")) {
                ValidateUtil.validMaxLength(json, "bc", 256, false);
                validateMutiEmail(json.getString("bc"), "bc");
            }
            if (json.containsKey("cc")) {
                ValidateUtil.validMaxLength(json, "cc", 256, false);
                validateMutiEmail(json.getString("cc"), "cc");
            }

            String emailAddress = json.getString("email").trim();
            String body = json.getString("body");
            UPushMessageModel emailMagModel = new UPushMessageModel();
            emailMagModel.setTo(emailAddress);
            emailMagModel.setSendType("MAIL");
            emailMagModel.setSubject(json.getString("subject"));
            emailMagModel.setBc(json.getString("bc"));
            emailMagModel.setCc(json.getString("cc"));
            String code = OAuth2SecurityUtil.generateFixLenthRandomString(6);
            String bodyFormat = MessageFormat.format(body, code);
            emailMagModel.setBody(bodyFormat);

            try {
                emailSender.pushMsg(emailMagModel);
            } catch (Exception e) {
                throw new ApiException(ErrorCode.OAUTH_PUSH_MSG_ERROR);
            }
            RedisUtil.put(json.getString("email"), code, 5 * 60);

        } else {
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }
        return SUCCESS;
    }

    @RequestMapping(value = "/api/verification")
    public String apiOnlineTest(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object obj = requestMsg.getData();
        if (obj instanceof JSONObject) {
            JSONObject json = (JSONObject) obj;
            ValidateUtil.validNotNull(json, "token");
            ValidateUtil.validNotNull(json, "clientSecret");
            ValidateUtil.validNotNull(json, "input");

            if (StringUtils.isBlank(requestMsg.getApp_key())) {
                requestMsg.setApp_key(StringUtils.EMPTY);
            }
            String token = json.getString("token");
            String clientSecret = json.getString("clientSecret");
            Object input = json.get("input");

            if (input instanceof JSONObject) {
                JSONObject inputJson = JSONObject.parseObject(input.toString());

                RequestMsg newRequestMsg = JSONObject.toJavaObject(inputJson, RequestMsg.class);

                String userEncryptStr = SignUtil.getSignStringByRequestMsg(newRequestMsg, token);
                String userSign = SignUtil.getSign(userEncryptStr);

                String clientEncryptStr = SignUtil.getSignStringByRequestMsg(newRequestMsg, clientSecret);
                String clientSign = SignUtil.getSign(clientEncryptStr);

                Map<String, Object> data = new HashMap<String, Object>();
                data.put("sign", userSign);
                data.put("userEncryptString", userEncryptStr);
                data.put("clientSign", clientSign);
                data.put("clientEncryptString", clientEncryptStr);

                responseMsg.setData(data);

            } else {
                throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "input");
            }

        } else {
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }

        return SUCCESS;

    }

    private void validateMutiEmail(String input, String fieldName) {
        String[] split = null;
        if (input.contains(";")) {
            split = input.split(";");
        } else if (input.contains(",")) {
            split = input.split(",");
        }
        if (split != null && split.length > 0) {
            for (String string : split) {
                validateEmail(string, fieldName);
            }
        }

    }

    /**
     * 邮件格式校验，数字字母开头
     * 
     * @param email
     * @param fieldName
     */
    private void validateEmail(String email, String fieldName) {
        String reg = "^^[A-Za-z0-9]+([-_.][A-Za-z0-9]+)*@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";
        Pattern p = Pattern.compile(reg);
        Matcher m = p.matcher(email);
        if (!m.matches()) {
            throw new ApiException(ErrorCode.FEILD_NOT_MATCH, fieldName);
        }

    }

}
